package com.bestcem.xm.deliver.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bestcem.bp.xm.user.grpc.v1.services.Group;
import com.bestcem.xm.common.core.exception.BusinessException;
import com.bestcem.xm.component.mybatis.base.ResultPage;
import com.bestcem.xm.component.mybatis.service.impl.XmServiceImpl;
import com.bestcem.xm.component.security.context.SecurityContextHolder;
import com.bestcem.xm.componet.filestorage.service.StorageService;
import com.bestcem.xm.componet.redis.service.RedisService;
import com.bestcem.xm.deliver.controller.v2.param.*;
import com.bestcem.xm.deliver.controller.v2.vo.DeliverStoreVo;
import com.bestcem.xm.deliver.controller.v2.vo.DeliverVo;
import com.bestcem.xm.deliver.controller.v2.vo.SurveyDeliverPageVo;
import com.bestcem.xm.deliver.convert.DeliverConvertMapper;
import com.bestcem.xm.deliver.entity.*;
import com.bestcem.xm.deliver.grpc.client.QdesGrpcClient;
import com.bestcem.xm.deliver.grpc.client.SurveyGrpcClient;
import com.bestcem.xm.deliver.grpc.client.UserGrpcClient;
import com.bestcem.xm.deliver.mapper.*;
import com.bestcem.xm.deliver.service.DeliverDefaultDeliverService;
import com.bestcem.xm.deliver.service.DeliverDeliverService;
import com.bestcem.xm.deliver.service.ServiceSequenceService;
import com.bestcem.xm.deliver.util.PageUtil;
import com.bestcem.xm.qdes.grpc.v1.services.Project;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.bestcem.xm.deliver.enums.DeliverTtypeEnum.*;
import static com.bestcem.xm.deliver.enums.RespondentStatusEnum.RESPONDENT_STATUS_BEGIN;
import static com.bestcem.xm.deliver.enums.RespondentStatusEnum.RESPONDENT_STATUS_FINISH;
import static com.bestcem.xm.deliver.grpc.v1.services.DeliverTtype.DELIVER_TTYPE_DEFAULT;
import static com.bestcem.xm.deliver.grpc.v1.services.DeliverTtype.DELIVER_TTYPE_DEFAULT_STORE;
import static com.bestcem.xm.deliver.grpc.v1.services.SurveyRegionTtype.SURVEYREGION_TTYPE_GLOBAL;

/**
 * @author been
 * @description 针对表【ds_deliver_defaultdeliver】的数据库操作Service实现
 * @createDate 2022-11-07 13:49:46
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DeliverDefaultDeliverServiceImpl extends XmServiceImpl<DeliverDefaultDeliverMapper, DeliverDefaultDeliver> implements DeliverDefaultDeliverService {

    private @NonNull DeliverConvertMapper deliverConvertMapper;

    private @NonNull DeliverSurveyDeliverMapper deliverSurveyDeliverMapper;
    private @NonNull DeliverDeliverMapper deliverDeliverMapper;
    private @NonNull DeliverSurveyRegionMapper deliverSurveyRegionMapper;
    private @NonNull DeliverDefaultDeliverStoreMapper deliverStoreMapper;
    private @NonNull DeliverWechatmpDeliverMapper wechatMpdeliverMapper;
    private @NonNull DeliverDefaultDeliverMapper defaultDeliverMapper;
    private @NonNull DeliverCustomLinkDeliverMapper customLinkDeliverMapper;

    private @NonNull ServiceSequenceService serviceSequenceService;
    private @NonNull DeliverDeliverService deliverDeliverService;
    private @NonNull RedisService redisService;
    //private @NonNull OssService ossService;
    private @NonNull StorageService storageService;

    private @NonNull QdesGrpcClient qdesGrpcClient;
    private @NonNull UserGrpcClient userGrpcClient;
    private @NonNull SurveyGrpcClient surveyGrpcClient;

    @Override
    public DeliverVo getDefaultDeliver(String projectId, String userId, String orgId) {
        log.info("Now to GetDefaultDeliver, id = {}, userId = {}", projectId, userId);
        // 获取默认投放
        LambdaQueryWrapper<DeliverSurveyDeliver> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(DeliverSurveyDeliver::getSurveyId, projectId);
        List<DeliverSurveyDeliver> delivers = deliverSurveyDeliverMapper.selectList(wrapper);
        List<String> deliverIds = delivers.stream().map(DeliverSurveyDeliver::getDeliverId).collect(Collectors.toList());
        LambdaQueryWrapper<DeliverDeliver> dwrapper = Wrappers.lambdaQuery();
        dwrapper.eq(DeliverDeliver::getTtype, DELIVER_TTYPE_DEFAULT.getNumber());
        if (CollectionUtils.isNotEmpty(deliverIds)) {
            dwrapper.in(DeliverDeliver::getId, deliverIds);
        }
        dwrapper.last("limit 1");
        DeliverDeliver deliver = deliverDeliverMapper.selectOne(dwrapper);
        // 如果没有默认投放 返回空
        if (deliver == null) {
            return new DeliverVo();
        }
        DeliverVo deliverVo = deliverConvertMapper.deliver2Vo(deliver);
        // 获取survey
        Project survey = qdesGrpcClient.getProject(projectId);
        // 问卷分享卡片：卡片标题和背景图片
        JSONObject customAttr = StringUtils.isEmpty(survey.getCustomAttr()) ? new JSONObject() : JSONObject.parseObject(survey.getCustomAttr());
        deliverVo.setWxCardShareTitle(StringUtils.isEmpty(customAttr.getString("wxCardShare_title")) ? survey.getTitle() : customAttr.getString("wxCardShare_title"));
        //deliverVo.setWxCardShareBgImg(StringUtils.isEmpty(customAttr.getString("wxCardShare_bg_img")) ? ossService.getCdn() + ossService.getFilePrefix() + "survey/bg_card_share_v1.png" : customAttr.getString("wxCardShare_bg_img"));
        deliverVo.setWxCardShareBgImg(StringUtils.isEmpty(customAttr.getString("wxCardShare_bg_img")) ? storageService.getPropertiesValueBy(null, "domain") + storageService.getPropertiesValueBy(null, "base-path") + "survey/bg_card_share_v1.png" : customAttr.getString("wxCardShare_bg_img"));

        // 获取二维码存放路径
        String fileUrl = deliverDeliverService.getQrcodePath(orgId, survey, deliver.getId(), null);
        if (StringUtils.isEmpty(fileUrl)) {
            throw new BusinessException("Download file name does not exist");
        }
        // java可以直接下载
        // 获取全局(通用)的survey_region
        LambdaQueryWrapper<DeliverDefaultDeliver> defaultWrapper = Wrappers.lambdaQuery();
        defaultWrapper.eq(DeliverDefaultDeliver::getSurveyId, projectId)
                .eq(DeliverDefaultDeliver::getDeliverId, deliver.getId())
                .eq(DeliverDefaultDeliver::getTtype, SURVEYREGION_TTYPE_GLOBAL.getNumber())
                .last("limit 1");
        DeliverDefaultDeliver surveyRegion = baseMapper.selectOne(defaultWrapper);

        if (surveyRegion != null) {
            // 投放连接
            deliverVo.setLink(surveyRegion.getLink());
            deliverVo.setDefaultDeliverId(surveyRegion.getId());
            deliverVo.setDisable(surveyRegion.getDisable());
        }
        // 二维码图片地址
        deliverVo.setUrl(fileUrl);
        return deliverVo;
    }

    @Override
    public JSONObject getDefaultSequence(SequenceParam param) {
        if (StringUtils.isEmpty(param.getProjectId()) || param.getTtype() == null) {
            throw new BusinessException("缺少参数");
        }
        Project survey = qdesGrpcClient.getProject(param.getProjectId());
        if (survey == null) {
            throw new BusinessException("project not exist");
        }

        // 获取当前redis中的投放序号
        Integer currentSequence = serviceSequenceService.getCurrentSequence("deliver:default_name_" + param.getProjectId() + "_" + param.getTtype());
        if (currentSequence == null) {
            currentSequence = serviceSequenceService.getSequence("deliver:default_name_" + param.getProjectId() + "_" + param.getTtype(), 1);
        }
        JSONObject seqJson = new JSONObject();
        seqJson.put("sequence", currentSequence);
        return seqJson;
    }

    @Override
    public ResultPage<SurveyDeliverPageVo> getSelectDeliver(Page<SurveyDeliverPageVo> page, SelectParam param) {
        String projectId = param.getSurveyId();
        if (StringUtils.isEmpty(projectId)) {
            throw new BusinessException("缺少参数survey_id");
        }

        return doPage(page, param);
    }

    private ResultPage<SurveyDeliverPageVo> doPage(Page<SurveyDeliverPageVo> page, SelectParam param) {
        // 过滤掉默认投放
        DeliverDeliver defaultDeliver = getDefaultQrcodeDeliver(param.getSurveyId());
        if (defaultDeliver != null) {
            param.setIgnoreId(defaultDeliver.getId());
        }
        Page<SurveyDeliverPageVo> pages = deliverDeliverMapper.pageDeliver(page, param);

        Project project = qdesGrpcClient.getProject(param.getSurveyId());
        if (project == null) {
            throw new BusinessException("项目不存在");
        }
        List<SurveyDeliverPageVo> records = pages.getRecords();
        records.forEach(record -> {
            deliverDeliverService.itemTofront(record, project);
            record.setFinished(getDeliverRespTotalCount(record.getDeliverId(), param.getSurveyId()));
            int ttype = record.getDeliverDocs().getTtype();
            if (ttype == DELIVER_TTYPE_SMS.getValue() || ttype == DELIVER_TTYPE_EMAIL.getValue()
                    || ttype == DELIVER_TTYPE_WECHATMP.getValue()) {
                record.setPlaned(deliverDeliverService.getDeliverPlanTotalCount(record.getDeliverId(), ttype));
            }
            if (ttype == DELIVER_TTYPE_WECHATMP.getValue()) {
                LambdaQueryWrapper<DeliverWechatmpDeliver> wrapper = Wrappers.lambdaQuery();
                wrapper.eq(DeliverWechatmpDeliver::getDeliverId, record.getDeliverId()).last("limit 1");
                DeliverWechatmpDeliver wechatDeliver = wechatMpdeliverMapper.selectOne(wrapper);
                if (wechatDeliver != null) {
                    record.setMpName(wechatDeliver.getMpName());
                    record.setMpTtype(wechatDeliver.getMpTtype());
                }
            } else if (ttype == DELIVER_TTYPE_CUSTOM_LINK.getValue()) {
                DeliverCustomLinkDeliver linkDeliver = customLinkDeliverMapper.selectOne(
                        new LambdaQueryWrapper<DeliverCustomLinkDeliver>()
                                .eq(DeliverCustomLinkDeliver::getDeliverId, record.getDeliverId()).last("limit 1"));
                if (linkDeliver != null) {
                    record.setLinkAgingType(linkDeliver.getLinkAgingType());
                    record.setLinkAgingTime(linkDeliver.getLinkAgingTime());
                    record.setReqMethod(linkDeliver.getReqMethod());
                    record.setIsDelay(0);
                }
            }
            record.setProcessing(getDeliverProcessingTotalCount(record.getDeliverId(), param.getSurveyId()));
        });

        return PageUtil.getResultPage(pages.getCurrent(), pages.getTotal(), records);
    }

    private int getDeliverProcessingTotalCount(String deliverId, String projectId) {
        // 获取一个投放中答题状态是成功完成的数量
        return surveyGrpcClient.getDeliverRspdAmount(deliverId, null, null, null,
                RESPONDENT_STATUS_BEGIN.getValue(), null, projectId);
    }

    private int getDeliverRespTotalCount(String deliverId, String projectId) {
        // 获取一个投放中答题状态是成功完成的数量
        return surveyGrpcClient.getDeliverRspdAmount(deliverId, null, null, null,
                RESPONDENT_STATUS_FINISH.getValue(), null, projectId);
    }

    // 获取项目默认二维码投放
    private DeliverDeliver getDefaultQrcodeDeliver(String projectId) {
        LambdaQueryWrapper<DeliverSurveyDeliver> defaultWrapper = Wrappers.lambdaQuery();
        defaultWrapper.eq(DeliverSurveyDeliver::getSurveyId, projectId);
        List<DeliverSurveyDeliver> surveyDelivers = deliverSurveyDeliverMapper.selectList(defaultWrapper);
        if (CollectionUtils.isEmpty(surveyDelivers)) {
            return null;
        }
        List<String> deliverIds = surveyDelivers.stream().map(DeliverSurveyDeliver::getDeliverId).collect(Collectors.toList());

        LambdaQueryWrapper<DeliverDeliver> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(DeliverDeliver::getTtype, DELIVER_TTYPE_DEFAULT.getNumber())
                .eq(DeliverDeliver::getId, deliverIds).last("limit 1");
        return deliverDeliverMapper.selectOne(wrapper);
    }

    @Override
    public JSONObject surveyRegionExist(String projectId, String userId, String orgId) {
        if (StringUtils.isEmpty(projectId)) {
            throw new BusinessException("缺少参数");
        }

        JSONObject reJson = new JSONObject();
        // 判断问卷项目是否存在二维码链接survey_region
        LambdaQueryWrapper<DeliverSurveyRegion> defaultWrapper = Wrappers.lambdaQuery();
        defaultWrapper.eq(DeliverSurveyRegion::getSurveyId, projectId).eq(DeliverSurveyRegion::getOrgId, orgId).last("limit 1");
        DeliverSurveyRegion surveyRegion = deliverSurveyRegionMapper.selectOne(defaultWrapper);
        if (surveyRegion != null) {
            reJson.put("is_survey_region", true);
        } else {
            reJson.put("is_survey_region", false);
        }
        return reJson;
    }

    @Override
    public JSONObject getDeliverStore(String projectId, String userId, String orgId) {
        if (StringUtils.isEmpty(projectId)) {
            throw new BusinessException("缺少参数");
        }
        // 获取默认投放
        LambdaQueryWrapper<DeliverSurveyDeliver> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(DeliverSurveyDeliver::getSurveyId, projectId);
        List<DeliverSurveyDeliver> delivers = deliverSurveyDeliverMapper.selectList(wrapper);
        List<String> deliverIds = delivers.stream().map(DeliverSurveyDeliver::getDeliverId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(deliverIds)) {
            return new JSONObject();
        }
        LambdaQueryWrapper<DeliverDeliver> dwrapper = Wrappers.lambdaQuery();
        dwrapper.eq(DeliverDeliver::getTtype, DELIVER_TTYPE_DEFAULT_STORE.getNumber()).in(DeliverDeliver::getId, deliverIds);
        dwrapper.last("limit 1");
        DeliverDeliver deliver = deliverDeliverMapper.selectOne(dwrapper);
        if (deliver == null) {
            return new JSONObject();
        }
        JSONObject reJson = new JSONObject();
        reJson.put("default_deliver_store_id", deliver.getId());
        return reJson;
    }

    @Override
    public JSONObject batchSwitch(String projectId, BatchSwitchParam batchSwitchParam) {
        // 获取deliver_store
        boolean full = batchSwitchParam.getFull();
        boolean disable = batchSwitchParam.getDisable();

        List<String> defaultDeliverStoreIdList = batchSwitchParam.getDefaultDeliverStoreIdList();
        if (full) {
            LambdaQueryWrapper<DeliverDefaultDeliverStore> defaultWrapper = Wrappers.lambdaQuery();
            defaultWrapper.eq(DeliverDefaultDeliverStore::getSurveyId, projectId);
            List<DeliverDefaultDeliverStore> deliverStores = deliverStoreMapper.selectList(defaultWrapper);
            defaultDeliverStoreIdList = deliverStores.stream().map(DeliverDefaultDeliverStore::getId).collect(Collectors.toList());
        }

        LambdaUpdateWrapper<DeliverDefaultDeliverStore> updateWrapper = new LambdaUpdateWrapper<>();
        //构造查询条件-更新
        updateWrapper.set(DeliverDefaultDeliverStore::getDisable, disable)
                .set(DeliverDefaultDeliverStore::getUpdatedDt, LocalDateTime.now())
                .in(DeliverDefaultDeliverStore::getId, defaultDeliverStoreIdList);
        deliverStoreMapper.update(null, updateWrapper);

        JSONObject reJson = new JSONObject();
        reJson.put("modified_count", defaultDeliverStoreIdList.size());
        return reJson;
    }

    @Override
    public JSONObject oneSwitch(String id, SwitchParam switchParam) {
        if (StringUtils.isEmpty(id)) {
            throw new BusinessException("缺少参数");
        }
        if (switchParam.getDisable() == null) {
            throw new BusinessException("缺少参数");
        }

        LambdaUpdateWrapper<DeliverDefaultDeliverStore> updateWrapper = new LambdaUpdateWrapper<>();
        //构造查询条件-更新
        updateWrapper.set(DeliverDefaultDeliverStore::getDisable, switchParam.getDisable())
                .set(DeliverDefaultDeliverStore::getUpdatedDt, LocalDateTime.now())
                .eq(DeliverDefaultDeliverStore::getId, id);
        deliverStoreMapper.update(null, updateWrapper);

        JSONObject reJson = new JSONObject();
        reJson.put("id", id);
        return reJson;
    }

    @Override
    public ResultPage<DeliverStoreVo> getStorePage(Page<DeliverDefaultDeliverStore> page, GetStorePageParam param) {
        LambdaQueryWrapper<DeliverDefaultDeliverStore> defaultWrapper = Wrappers.lambdaQuery();
        defaultWrapper.eq(DeliverDefaultDeliverStore::getOrgId, param.getOrgId());
        if (StringUtils.isNotEmpty(param.getDeliverId())) {
            defaultWrapper.eq(DeliverDefaultDeliverStore::getDeliverId, param.getDeliverId());
        }
        if (param.getStatus() != null) {
            defaultWrapper.eq(DeliverDefaultDeliverStore::getStatus, param.getStatus());
        }
        if (param.getTtype() != null) {
            defaultWrapper.eq(DeliverDefaultDeliverStore::getTtype, param.getTtype());
        }
        if (StringUtils.isNotEmpty(param.getSearch())) {
            defaultWrapper.like(DeliverDefaultDeliverStore::getTitle, param.getSearch());
        }
        defaultWrapper.orderByDesc(DeliverDefaultDeliverStore::getCreatedDt);

        Page<DeliverDefaultDeliverStore> pageResult = deliverStoreMapper.selectPage(page, defaultWrapper);
        List<DeliverDefaultDeliverStore> stores = pageResult.getRecords();
        List<DeliverStoreVo> storeVos = new ArrayList<>();
        // 获取suevey
        Project project = qdesGrpcClient.getProject(param.getSurveyId());
        if (project == null) {
            throw new BusinessException("项目不存在");
        }
        // 无需判断aging.current_page_num == 1，区别只是cache=True是否有缓存，不需要
        stores.forEach(store -> {
            DeliverStoreVo storeVo = deliverConvertMapper.store2Vo(store);
            storeVo.setFinished(deliverDeliverService.getDeliverRspdAmount(storeVo.getDeliverId(), storeVo
                            .getGroupId(), null, null,
                    RESPONDENT_STATUS_FINISH.getValue(), null, param.getSurveyId()));
            Group group = userGrpcClient.getGroup(storeVo.getGroupId());
            // 获取二维码存放路径
            String fileUrl = deliverDeliverService.getQrcodePath(param.getOrgId(), project, param.getDeliverId(), group);
            storeVo.setUrl(fileUrl);
            storeVos.add(storeVo);
        });
        return PageUtil.getResultPage(page.getCurrent(), pageResult.getTotal(), storeVos);
    }

    @Override
    public JSONObject getDeliverTaskProcess(String taskId, String userId, String orgId) {
        // 返回task状态
        JSONObject taskJson = new JSONObject();
        if (ObjectUtil.isEmpty(redisService.get(taskId + ":status"))) {
            taskJson.put("status", "PENDING");
        } else {
            taskJson.put("status", redisService.get(taskId + ":status"));
        }
        return taskJson;
    }


    @Override
    public JSONObject getSurveyDeliverPage(GetSurveyDeliverParam param) {
        String orgId = SecurityContextHolder.getOrgId();
        LambdaQueryWrapper<DeliverSurveyDeliver> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DeliverSurveyDeliver::getSurveyId, param.getSurveyId())
                .eq(DeliverSurveyDeliver::getOrgId, orgId);
        List<String> deliverIdList = deliverSurveyDeliverMapper.selectList(queryWrapper).stream().map(DeliverSurveyDeliver::getDeliverId).collect(Collectors.toList());
        List<DeliverDeliver> deliverList = deliverDeliverMapper.selectBatchIds(deliverIdList);
        JSONObject map = new JSONObject();
        map.put("total_count", deliverList.size());
        map.put("rows", deliverList);
        map.put("page", 1);
        return map;
    }

    @Override
    public JSONObject defaultOneSwitch(String id, SwitchParam switchParam) {
        log.info("Now to defaultOneSwitch");
        // 更新DefaultDeliver
        Boolean disable = switchParam.getDisable();
        if (disable == null) {
            throw new BusinessException("缺少参数");
        }
        // 更新投放使能
        LambdaUpdateWrapper<DeliverDefaultDeliver> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(DeliverDefaultDeliver::getDisable, switchParam.getDisable())
                .set(DeliverDefaultDeliver::getUpdatedDt, LocalDateTime.now())
                .eq(DeliverDefaultDeliver::getId, id);
        defaultDeliverMapper.update(null, updateWrapper);
        JSONObject re = new JSONObject();
        re.put("id", id);
        return re;
    }
}




